#include"数据预处理.h"

double definite_integral(double** data, int s_point, int e_point)
{   //用来计算积分
    double integral = 0; // 最终的积分结果
    double dt = (data[e_point][0] - data[s_point][0]) / (e_point - s_point); // 使用梯形近似法，dt相当于每个长方体底边的宽度，单位微秒us
    int tmp = 0; // 计算积分循环中的计数器
    for (tmp = 0; tmp < e_point - s_point; tmp++)
    {
        integral += (data[s_point + tmp][2] * data[s_point + tmp][3] * dt); // 电流与电压的乘积，再乘以底边面积，计算积分大小
    }
    return integral;
}

int GetRow(char *filename)
{
    // 通过读取一次文件，获取文件一共有多少行
	char line[1024];
	int i = 0;
	FILE* stream = fopen(filename, "r");
	while(fgets(line, 1024, stream))
    {
		i++;
	}
	fclose(stream);
	return i;
}

int GetCol(char *filename)
{
    // 通过读取一次文件，获取文件一共有多少列
	char line[1024];
	int i = 0;
	FILE* stream = fopen(filename, "r");
	fgets(line, 1024, stream);
	char* token = strtok(line, ",");
	while(token)
    {
		token = strtok(NULL, ",");
		i++;
	}
	fclose(stream);
	return i;
}

void PrintTwoDimension(double** data, int row, int col)
{
    // 测试代码专用，用来将data二维数组的内容打印出来
	int i, j;
	for(i=1; i<row; i++)
    {
		for(j=0; j<col; j++)
        {
			printf("%f\t", data[i][j]);
		}
		printf("\n");
	}//打印的时候不打印第一行，因为第一行是每一列数据的名称
}

void PrintOneDimension(double in_out_put[])
{
    printf("in_out_put = [");
    for (int i = 0; i < 13; i++)
    {
        printf("%.2f", in_out_put[i]);
        if (i < 12)
            printf(", ");
    }
    printf("]\n");
}

double ** GetWaveData(char *file_in)
{
    // 读取csv文件中的波形数据的函数
    double **data;
    char line[1024]; // 逐行读取的时候存储每一行的数据
    int row, col; // 用来确定文件一共有多少行多少列
    row = GetRow(file_in); // 调用函数获取文件行数
    col = GetCol(file_in); // 调用函数获取文件列数
    data = (double **)malloc(row * sizeof(int *)); // 用来存储40w个数据的二维数组，[i][0]表示g_t，同理[i][1],[i][2],[i][3]
    for (int i = 0; i < row; ++i)
    {
        data[i] = (double *)malloc(col * sizeof(double));//动态申请二维数组
    }
    FILE* stream = fopen(file_in, "r");
	int i = 0;
	while (fgets(line, 1024, stream))//逐行读取
    {
    	int j = 0;
    	char *tok;
        char* tmp = _strdup(line);
        for (tok = strtok(line, ","); tok && *tok; j++, tok = strtok(NULL, ",\n"))
        {
            //这个大括号内执行字符串拆分操作 
        	data[i][j] = atof(tok);//转换成浮点数 
		}
        i++;
        free(tmp);
    }
    fclose(stream);//文件打开后要进行关闭操作
    // PrintTwoDimension(data, row, col);
    // printf("row = %d\n", row);
    // printf("col = %d\n", col);

    return data;
}

void GetInPut(double** data, int row, int col, double in_out_put[])
{
    // 根据CSV文件内容提取动态参数的函数
    int Vge_error = 0; // Vge波形是否有错误的判断参数
    int Vce_error = 0; // Vce波形是否有错误的判断参数
    int Ic_error = 0;  // Ic波形是否有错误的判断参数

    int t_1_on = 0;  // 第一次开通的时间所在列表中的下标
    int t_1_off = 0; // 第一次关断的时间所在列表中的下标
    int t_2_on = 0;  // 第二次开通的时间所在列表中的下标
    int t_2_off = 0; // 第而次关断的时间所在列表中的下标
    // 这四个时间点只是大致划分，还需要更精细计算

    int t_Ispike = 0;   // 电流尖峰出现位置对应列的下标
    int t_Istable = 0;  // 额定电流出现位置对应列的下标
    int t_Vspike = 0;   // 电流尖峰出现位置对应列的下标

    double Vge_stable = 0;  // 额定栅极电压(V)
    double Ic_stable = 0;   // 额定电流的大小(A)
    double Vce_stable = 0;  // 额定电压的大小(V)

    int t_off_09Vge = 0; // 第一次关断时，栅极电压Vge达到额定值90%的时间所在列表中的下标
    int t_off_01Vce = 0; // 第一次关断时，集射极电压Vce达到额定值10%的时间所在列表中的下标
    int t_off_09Ic = 0;  // 第一次关断时，集电极电流Ic达到额定值90%的时间所在列表中的下标
    int t_off_01Ic = 0;  // 第一次关断时，集电极电流Ic达到额定值10%的时间所在列表中的下标
    int t_off_002Ic = 0; // 第一次关断时，集电极电流Ic达到额定值2%的时间所在列表中的下标

    int t_on_01Vge = 0;  // 第二次开通时，栅极电压Vge达到额定值10%的时间所在列表中的下标
    int t_on_01Ic = 0;   // 第二次开通时，集电极电流Ic达到额定值10%的时间所在列表中的下标
    int t_on_09Ic = 0;   // 第二次开通时，集电极电流Ic达到额定值90%的时间所在列表中的下标
    int t_on_002Vce = 0; // 第二次开通时，集射极电压Vce达到额定值20%的时间所在列表中的下标

    double dertaI = 0; // 电流过充：尖峰电流与额定电流的差值 
    double didt = 0;   // 电流变化率：t_on_01Ic到t_on_09Ic之间的电流变化率
    double tdon = 0;   // 开通延时：t_on_01Vge到t_on_01Ic之间的时间差
    double tr = 0;     // 上升时间：t_on_01Ic到t_on_09Ic之间的时间差
    double Eon = 0;    // 开通损耗：t_on_01Ic到t_on_002Vce之间，集射极电压Vce与集电极电流Ic乘积的积分
    double dertaV = 0; // 电压过充：尖峰电压与额定电压的差值 
    double dvdt = 0;   // 电压变化率：t_off_09Ic到t_off_01Ic之间的电压变化率
    double tdoff = 0;  // 关断延时：t_off_09Vge到t_off_09Ic之间的时间差
    double tf = 0;     // 下降时间：t_off_09Ic到t_off_01Ic之间的时间差
    double Eoff = 0;   // 关断损耗：t_off_01Vce到t_off_002Ic之间，集射极电压Vce与集电极电流Ic乘积的积分

    double max_Vge = 0; // 栅极电压Vge最大值，用来判断Vge是否有问题
    double min_Vge = 0; // 栅极电压Vge最小值，用来判断Vge是否有问题
    //---------------t_1_on、t_1_off、t_2_on、t_2_off的获取------------------------------------
    for (int i = 1; i < row; i++)

    {
        if (max_Vge < data[i][1])
        {
            max_Vge = data[i][1];
        }
        else if (min_Vge > data[i][1])
        {
            min_Vge = data[i][1];
        }
    }
    // printf("max_Vge=%f\n", max_Vge); // 测试专用代码
    // printf("min_Vge=%f\n", min_Vge); // 测试专用代码
    if (max_Vge < 13 || min_Vge > -6)
    {   //先判断Vge波形是否正常
        printf("Vge可能存在开通关断电压不是-8~15V的异常，请检查。\n");
        Vge_error = 1;
    }
    else
    {   //在Vge正常的情况下，使用Vge大致得到两次的开关时间点
        //printf("Vge正常\n"); //再根据这4个时间节点进行更精细的计算
        int i = 0; //用来在之后的循环中确定各个时间节点位置的计数器。
        while (i < row)
        {
            if (data[i][1] > 13)
            {   // 找到第一个Vge大于13V的点，作为第一次开通的时间点
                t_1_on = i;
                break;
            }
            else{i++;}
        }
        while (i < row)
        {
            if (data[i][1] < 0)
            {   // 找到第一个Vge小于0V的点，作为第一次关断的时间点
                t_1_off = i;
                break;
            }
            else{i++;}
        }
        while (i < row)
        {
            if (data[i][1] > 13)
            {   // 找到第二个Vge大于13V的点，作为第二次开通的时间点
                t_2_on = i;
                break;
            }
            else{i++;}
        }
        while (i < row)
        {
            if (data[i][1] < 0)
            {   // 找到第二个Vge小于0V的点，作为第二次关断的时间点
                t_2_off = i;
                break;
            }
            else{i++;}
        }
        // printf("t_1_on:%d\n",t_1_on);
        // printf("t_1_off:%d\n",t_1_off);
        // printf("t_2_on:%d\n",t_2_on);
        // printf("t_2_off:%d\n",t_2_off);
        
    }
    //---------------------------------dertaI相关参数的获取------------------------------------
    for (int i = t_1_off; i < t_2_off; i++) // 电流尖峰在二开附近，只用找一关和二关之间就可以了
    {
        if (data[t_Ispike][3] < data[i][3])
        {
            t_Ispike = i; // 获取的是电流尖峰的数组下标
        }
    }
    for (int i = (t_1_on + t_1_off)/2; i < (t_1_off + t_2_on)/2; i++) // 电流平稳值在一关附近
    {
        if (data[t_Istable][3] < data[i][3])
        {
            t_Istable = i; // 获取的是电流平稳值的数组下标
        }
    }
    Ic_stable = data[t_Istable][3];
    dertaI = data[t_Ispike][3] - Ic_stable; // 计算电流差值，获得一个动态参数
    if (dertaI < 1 || data[t_Ispike][3] < 10)
    {
        Ic_error = 1;
        printf("Ic可能存在异常。");
    }
    // printf("t_Ispike=%d\n", t_Ispike);
    // printf("Ispike=%f\n", data[t_Ispike][3]);
    // printf("t_Istable=%d\n", t_Istable);
    // printf("Istable=%f\n", data[t_Istable][3]);
    //---------------------------------dertaV相关参数的获取------------------------------------
    int t_Vge_stable_l = (t_1_on + t_1_off)/2; // 计算Vge_stable时候的左起点，取一开和一关的中点
    double Vge_stable_sum = 0;
    for (int i = t_Vge_stable_l; i < t_Vge_stable_l + 400; i++)
    {   // 向右取400个参数取均值，以消除电压波动的影响，获取Vge的均值
        Vge_stable_sum += data[i][1];
    }
    Vge_stable = Vge_stable_sum / 400;

    int t_Vce_stable_l = t_1_on / 2; // 计算Vce_stable时候的左起点，取0和一开的中点
    double Vce_stable_sum = 0;
    for (int i = t_Vce_stable_l; i < t_Vce_stable_l + 400; i++)
    {   // 向右取400个参数取均值，以消除电压波动的影响，获取Vge的均值
        Vce_stable_sum += data[i][2];
    }
    Vce_stable = Vce_stable_sum / 400;

    for (int i = (t_2_on + t_2_off)/2; i < (t_2_off + row)/2; i++) // 电压尖峰在二关附近，只用找二开之后的值
    {
        if (data[t_Vspike][2] < data[i][2])
        {
            t_Vspike = i; // 获取的是电压尖峰的数组下标
        }
    }
    dertaV = data[t_Vspike][2] - Vce_stable;
    // printf("Vge_stable=%f\n", Vge_stable);
    // printf("Vce_stable=%f\n", Vce_stable);
    // printf("t_Vspike=%d\n", t_Vspike);
    // printf("Vspike=%f\n", data[t_Vspike][2]);
    // printf("dertaV=%f\n", dertaV);
    //---------------------------------第2部分关键时间点的获取----------------------------------
    // 用来获取第一次关断中90%Vge、10%Vce、90%Ic、10%Ic、2%Ic的位置
    // 以及第二次开通过程中10%Vge、10%Ic、90%Ic、2%Vce的位置
    // -------------------------以下为第一次关断过程中的关键参数点-------------------------------
    int i = (t_1_on + t_1_off)/2; //用来在之后的循环中确定各个时间节点位置的计数器。
    while (i < t_2_on)
    {
        if (data[i][1] < 0.9 * Vge_stable)
        {
            t_off_09Vge = i; // 确定90%Vge的位置
            break;
        }
        else{i++;}
    }
    i = (t_1_on + t_1_off)/2;
    while (i < t_2_on)
    {
        if (data[i][2] > 0.1 * Vce_stable)
        {
            t_off_01Vce = i; // 确定10%Vce的位置
            break;
        }
        else{i++;}
    }
    i = t_Istable;
    while (i < t_2_on)
    {
        if (data[i][3] < 0.9 * Ic_stable)
        {
            t_off_09Ic = i; // 确定90%Ic的位置
            break; 
        }
        else{i++;}
    }
    i = t_Istable;
    while (i < t_2_on)
    {
        if (data[i][3] < 0.1 * Ic_stable)
        {
            t_off_01Ic = i; // 确定10%Ic的位置
            break; 
        }
        else{i++;}
    }
    i = t_Istable;
    while (i < t_2_on)
    {
        if (data[i][3] < 0.02 * Ic_stable)
        {
            t_off_002Ic = i; // 确定2%Ic的位置
            break; 
        }
        else{i++;}
    }
    // -------------------------以下为第二次开通过程中的关键参数点-------------------------------
    i = (t_1_off + t_2_on)/2;
    while (i < t_2_off)
    {
        if (data[i][1] > 0.1 * Vge_stable)
        {
            t_on_01Vge = i; // 确定10%Vge的位置
            break;
        }
        else{i++;}
    }
    i = (t_1_off + t_2_on)/2;
    while (i < t_2_off)
    {
        if (data[i][3] > 0.1 * Ic_stable)
        {
            t_on_01Ic = i; // 确定10%Ic的位置
            break; 
        }
        else{i++;}
    }
    i = (t_1_off + t_2_on)/2;
    while (i < t_2_off)
    {
        if (data[i][3] > 0.9 * Ic_stable)
        {
            t_on_09Ic = i; // 确定90%Ic的位置
            break;
        }
        else{i++;}
    }
    i = (t_1_off + t_2_on)/2;
    while (i < t_2_off)
    {
        if (data[i][2] < 0.02 * Vce_stable)
        {
            t_on_002Vce = i; // 确定2%Vce的位置
            break;
        }
        else{i++;}
    }
    // printf("以下为第一次关断时关键时间点\n");
    // printf("一关时90%%Vge:%d(tdoff左侧)\n", t_off_09Vge);
    // printf("一关时10%%Vce:%d(Eoff左侧)\n", t_off_01Vce);
    // printf("一关时90%% Ic:%d(tdoff右侧和tf左侧)\n", t_off_09Ic);
    // printf("一关时10%% Ic:%d(tf右侧)\n", t_off_01Ic);
    // printf("一关时 2%% Ic:%d(Eoff右侧)\n", t_off_002Ic);
    // printf("以下为第二次开通时关键时间点\n");
    // printf("二开时10%%Vge:%d(tdon左侧)\n", t_on_01Vge);
    // printf("二开时10%% Ic:%d(tdon右侧,tr左侧,Eon左侧)\n", t_on_01Ic);
    // printf("二开时90%% Ic:%d(tr右侧)\n", t_on_09Ic);
    // printf("二开时2%% Vce:%d(Eon右侧)\n", t_on_002Vce);
    // -------------------------各时间点已经获取，接下来计算动态参数-------------------------------
    didt = ((data[t_on_09Ic][3] - data[t_on_01Ic][3]) / (data[t_on_09Ic][0] - data[t_on_01Ic][0])); 
    tdon = data[t_on_01Ic][0] - data[t_on_01Vge][0];
    tr = data[t_on_09Ic][0] - data[t_on_01Ic][0];
    Eon = definite_integral(data, t_on_01Ic, t_on_002Vce);
    dvdt = ((data[t_off_01Ic][2] - data[t_off_09Ic][2]) / (data[t_off_01Ic][0] - data[t_off_09Ic][0])); ;
    tdoff = data[t_off_09Ic][0] - data[t_off_09Vge][0];
    tf = data[t_off_01Ic][0] - data[t_off_09Ic][0];
    Eoff = definite_integral(data, t_off_01Vce, t_off_002Ic);
     printf("开通参数1:电流过充   dertaI = %.2f(A)\n",dertaI);
     printf("开通参数2:电流变化率   didt = %.2f(A/us)\n",didt);
     printf("开通参数3:开通延时     tdon = %.2f(us)\n",tdon);
     printf("开通参数4:上升时间       tr = %.2f(us)\n",tr);
     printf("开通参数5:开通损耗      Eon = %.2f(uJ)\n",Eon);
     printf("关断参数1:电压过充   dertaV = %.2f(V)\n",dertaV);
     printf("关断参数2:电压变化率   dvdt = %.2f(V/us)\n",dvdt);
     printf("关断参数3:关断延时    tdoff = %.2f(us)\n",tdoff);
     printf("关断参数4:下降时间       tf = %.2f(us)\n",tf);
     printf("关断参数5:关断损耗     Eoff = %.2f(uJ)\n",Eoff);
     in_out_put[0] = dertaI;
     in_out_put[1] = didt;
     in_out_put[2] = tdon;
     in_out_put[3] = tr;
     in_out_put[4] = Eon;
     in_out_put[5] = dertaV;
     in_out_put[6] = dvdt;
     in_out_put[7] = tdoff;
     in_out_put[8] = tf;
     in_out_put[9] = Eoff;
}
// 以上部分已写完

void DrawWaveData(double** data)
{
    // 绘制波形的函数
    printf("执行DrawWaveData函数,还没有写完\n");
}
void GetOutPut()
{
    // 根据CSV文件名提取驱动电路参数的函数
    printf("执行GetOutPut函数,还没有写完\n");
}

void FileWrite()
{
    // 将动态参数和驱动电路参数写入CSV文件的函数
    printf("执行FileWrite函数,还没有写完\n");
}
